#!/usr/bin/env python
# encoding: utf-8
# @author: Lin Han
# @contact: voldemort22@126.com
# @file: deprecated_app.py
# @time: 2021/3/24 19:27
# @desc:
import json
import time

import requests
from fastapi import APIRouter, File, UploadFile, Request, BackgroundTasks

from application.standard_part.crud import generate_standard_part_data
from application.standard_part.queryModels import StandardPartChangeSize, UploadStandardPartModel
from background.background_update import update_04
from models.queryModels import MultipleConditionQueryStandardParts, UpdateOneStandardPart
from models.responseModels import ResponseDict
from utils.mongo_tools import update_mongo_value, retrieve_one_mongo_value, create_one_mongo_value, retrieve_mongo_values, delete_mongo_value, retrieve_all_mongo_values, standard_part_number_generator
from utils.oss.oss_tools import upload_file_to_oss
from utils.utils import create_folder, write_file, read_json, save_json
from views.configs import *
from views.crud import upload_to_aliyun_standard_part_model, keyword_search_standard_clamp, separate_page, send_to_message_queue, keyword_search_standard_part

standard_part_router = APIRouter(
    prefix="/api/standard_part",
    tags=["standard_part"],
)


@standard_part_router.post("/v1/standard_part")
async def upload_standard_part(
        category: str = File(...),
        file: UploadFile = File(...),
        desc: str = File(...),
        version: str = File(...),
):
    """
    上传标准零件的json格式文件，并创建一条数据。

    - :return:
    """
    isFeature: bool = False
    isFlag: bool = False
    folder = create_folder()
    file_path = f"{folder}/{file.filename}"
    # 写入文件
    write_file(file_path=file_path, file=file)
    jsonData = read_json(file_path)
    standardPartModel = upload_to_aliyun_standard_part_model(
        filename=file_path,
        jsonData=jsonData,
        category=category,
        desc=desc,
        version=version,
        isFeature=isFeature,
        isFlag=isFlag,
    )
    create_one_mongo_value(
        standardPartModel,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )
    model = {"data": standardPartModel["number"], "status": 1}
    return model


@standard_part_router.post("/v1/standard_parts", response_model=ResponseDict)
async def multiple_condition_query_standard_parts(queryModel: MultipleConditionQueryStandardParts):
    """
    # Deprecated
    ## 多条件筛选查询标准零件

    - :param queryModel:
    - :return:
    """
    model = {"data": {"result": []}}
    result = retrieve_mongo_values(
        {},
        "4",
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )
    result = keyword_search_standard_clamp(queryModel, result)
    model["data"]["total"] = len(result)
    if len(result) > 0:
        # 如果isTotal为True，意味着进入了详情页面，则不需要分页了。
        if not queryModel.isTotal:
            model["data"]["result"] = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        else:
            model["data"]["result"] = result
    model["status"] = 1
    return model


@standard_part_router.delete("/v1/standard_part")
async def delete_standard_part(number: str):
    """
    # Deprecated
    ## 删除一条数据

    - :param number:
    - :return:
    """
    model = {"data": False}
    result = delete_mongo_value(
        number=number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )
    if result.deleted_count > 0:
        model["data"] = True
        model["status"] = 1
    else:
        model["status"] = 0
    return model


@standard_part_router.get("/v1/standard_part_version", response_model=ResponseDict)
async def get_standard_part_version():
    """
    获取 标准零件 所有的版本号

    - :return:
    """
    model = {"data": {}}
    result = retrieve_mongo_values(
        {},
        "4",
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )
    version_list = []
    for i in result:
        if "version" in i.keys():
            if i["version"] not in version_list:
                version_list.append(i["version"])
    model["data"]["version"] = version_list
    model["status"] = 1
    return model


@standard_part_router.put("/v1/standard_part")
async def update_standard_part(queryModel: UpdateOneStandardPart):
    """
    更新 标准零件的相关信息

    - :param oneInfo:
    - :return:
    """
    model = {}
    updateInfo = {
        "$set": {
            "version": queryModel.version,
            "name": queryModel.name,
            "desc": queryModel.desc,
        }
    }
    update_mongo_value(
        {"number": queryModel.number},
        updateInfo,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )
    model["data"] = True
    model["status"] = 1
    return model


@standard_part_router.get("/v1/standard_part")
async def retrieve_history_part(number: str):
    """
    # Deprecated
    ## 返回一条标准零件的完整信息

    - :param number: 编号
    - :return:
    """
    model = {"data": {}}
    original_data = retrieve_one_mongo_value(number, database_name=MONGO_DATABASE_NAME,
                                             collection_name=STANDARD_PART_COLLECTION)
    try:
        model["data"] = original_data[0]
        model["status"] = 1
    except:
        model["status"] = 0
    return model


@standard_part_router.get("/v1/standard_part_stl_file")
async def get_standard_part_stl_file(number: str):
    """
    显示标准零件stl文件接口（给的是oss地址）

    - :param number: 编号
    - :return:
    """
    model = {"data": ""}
    # retrieve_one_mongo_value返回的是一个只有一个元素的列表，取第一个
    original_data = retrieve_one_mongo_value(
        number=number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )
    if len(original_data) > 0:
        # 标准夹具现阶段是用stl文件来显示，后续考虑换成gltf
        model["data"] = original_data[0]["file"][STL_OSS_ADDRESS]
    model["status"] = 1
    return model


@standard_part_router.post("/v2/standard_part")
async def upload_v2(request: Request, queryModel: UploadStandardPartModel):
    """
    ## 上传标准零件模型
    :param request:
    :param queryModel:
    :return:
    """
    number = standard_part_number_generator()
    standard_clamp = generate_standard_part_data(number, file_path=queryModel.jsonAliOssAddress, desc=queryModel.desc, version=queryModel.version, category=queryModel.category)

    await request.app.state.redis.set(standard_clamp["number"], json.dumps(standard_clamp))

    create_one_mongo_value(standard_clamp, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
    send_to_message_queue(number, queue=STANDARD_PART_QUEUE)

    model = {"data": number, "status": 1}
    return model


@standard_part_router.put("/v2/standard_part")
async def update_standard_part_v2(request: Request, queryModel: UpdateOneStandardPart):
    """
    更新 标准零件的相关信息v2版本。

    - :param queryModel:
    - :return:
    """
    model = {}
    updateInfo = {
        "$set": {
            "version": queryModel.version,
            "name": queryModel.name,
            "desc": queryModel.desc,
            "partFunction": queryModel.partFunction,
        }
    }
    update_mongo_value(
        {"number": queryModel.number},
        updateInfo,
        collection_name=STANDARD_PART_COLLECTION,
    )

    standard_part = retrieve_one_mongo_value(number=queryModel.number, collection_name=STANDARD_PART_COLLECTION)

    await request.app.state.redis.set(queryModel.number, json.dumps(standard_part))
    model["data"] = True
    model["status"] = 1
    return model


@standard_part_router.post("/v2/standard_parts", response_model=ResponseDict)
async def multiple_condition_query_standard_parts_v2(request: Request, queryModel: MultipleConditionQueryStandardParts):
    """
    ## 多条件筛选查询标准零件v2版


    - :param queryModel:
    - :return:
    """
    try:
        standard_part_number_list = await request.app.state.redis.get("standard_part")
        standard_part_number_list = json.loads(standard_part_number_list)
        standard_part_list = await request.app.state.redis.mget(*standard_part_number_list)
        result = [json.loads(i) for i in standard_part_list]
    except:
        result = retrieve_all_mongo_values({}, collection_name=STANDARD_PART_COLLECTION)
        standard_part_number_list = [i['number'] for i in result]
        await request.app.state.redis.set("standard_part", json.dumps(standard_part_number_list))
        for i in result:
            await request.app.state.redis.set(i["number"], json.dumps(i))

    result = keyword_search_standard_part(queryModel, result)
    if len(result) > 0:
        total = len(result)
        result = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        model = {
            "data": {
                "result": result,
                "total": total,
            },
            "status": 1,
        }
    else:
        model = {"data": {}, "status": 0}
    return model


@standard_part_router.delete("/v2/standard_part")
async def delete_standard_part_v2(request: Request, number: str, background_task: BackgroundTasks):
    """
    ## 删除一条数据

    - :param number:
    - :return:
    """
    try:
        await request.app.state.redis.delete(number)
    except:
        pass

    model = {"data": False}
    try:
        result = delete_mongo_value(
            number=number,
            collection_name=STANDARD_PART_COLLECTION,
        )
        background_task.add_task(update_04)
        if result.deleted_count > 0:
            model["data"] = True
            model["status"] = 1
        else:
            model["status"] = 0
    except:
        model["status"] = 0
    return model


@standard_part_router.get("/v2/standard_part")
async def retrieve_history_part_v2(request: Request, number: str):
    """
    ## 返回一条标准零件的完整信息

    - :param number: 编号
    - :return:
    """
    model = {"data": {}}
    try:
        standard_part = await request.app.state.redis.get(number)
        standard_part = json.loads(standard_part)
    except:
        standard_part = retrieve_one_mongo_value(number, collection_name=STANDARD_PART_COLLECTION)[0]
        await request.app.state.redis.set(number, json.dumps(standard_part))

    try:
        model["data"] = standard_part
        model["status"] = 1
    except:
        model["status"] = 0
    return model
